From 67b893c5f8be66c316189ed73692093accfb1e9a Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Mon, 15 Feb 2016 06:50:22 +0100 Subject: [PATCH] win32 theme: Add a way to query border of theme parts --- gtk/gtkcssnumbervalue.c | 12 ++++++++-- gtk/gtkcsswin32sizevalue.c | 41 ++++++++++++++++++++++++++++++++-- gtk/gtkwin32draw.c | 27 ++++++++++++++++++++--- gtk/gtkwin32drawprivate.h | 6 +++++ gtk/gtkwin32theme.c | 45 ++++++++++++++++++++++++++++++++++++++ gtk/gtkwin32themeprivate.h | 4 ++++ 6 files changed, 128 insertions(+), 7 deletions(-) diff --git a/gtk/gtkcssnumbervalue.c b/gtk/gtkcssnumbervalue.c index e8256c0cf7..54e1d1c006 100644 --- a/gtk/gtkcssnumbervalue.c +++ b/gtk/gtkcssnumbervalue.c @@ -133,7 +133,11 @@ gtk_css_number_value_can_parse (GtkCssParser *parser) || _gtk_css_parser_has_prefix (parser, "calc") || _gtk_css_parser_has_prefix (parser, "-gtk-win32-size") || _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-width") - || _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-height"); + || _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-height") + || _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-top") + || _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-left") + || _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-bottom") + || _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-right"); } GtkCssValue * @@ -144,7 +148,11 @@ _gtk_css_number_value_parse (GtkCssParser *parser, return gtk_css_calc_value_parse (parser, flags); if (_gtk_css_parser_has_prefix (parser, "-gtk-win32-size") || _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-width") || - _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-height")) + _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-height") || + _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-top") || + _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-left") || + _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-bottom") || + _gtk_css_parser_has_prefix (parser, "-gtk-win32-part-border-right")) return gtk_css_win32_size_value_parse (parser, flags); return gtk_css_dimension_value_parse (parser, flags); diff --git a/gtk/gtkcsswin32sizevalue.c b/gtk/gtkcsswin32sizevalue.c index 7c35d37902..9497c9c7f5 100644 --- a/gtk/gtkcsswin32sizevalue.c +++ b/gtk/gtkcsswin32sizevalue.c @@ -24,13 +24,21 @@ typedef enum { GTK_WIN32_SIZE, GTK_WIN32_PART_WIDTH, - GTK_WIN32_PART_HEIGHT + GTK_WIN32_PART_HEIGHT, + GTK_WIN32_PART_BORDER_TOP, + GTK_WIN32_PART_BORDER_RIGHT, + GTK_WIN32_PART_BORDER_BOTTOM, + GTK_WIN32_PART_BORDER_LEFT } GtkWin32SizeType; static const char *css_value_names[] = { "-gtk-win32-size(", "-gtk-win32-part-width(", - "-gtk-win32-part-height(" + "-gtk-win32-part-height(", + "-gtk-win32-part-border-top(", + "-gtk-win32-part-border-right(", + "-gtk-win32-part-border-bottom(", + "-gtk-win32-part-border-left(" }; struct _GtkCssValue { @@ -63,6 +71,7 @@ gtk_css_value_win32_size_free (GtkCssValue *value) static int gtk_css_value_win32_compute_size (const GtkCssValue *value) { + GtkBorder border; int size; switch (value->type) @@ -78,6 +87,26 @@ gtk_css_value_win32_compute_size (const GtkCssValue *value) gtk_win32_theme_get_part_size (value->theme, value->val.part.part, value->val.part.state, NULL, &size); break; + case GTK_WIN32_PART_BORDER_TOP: + gtk_win32_theme_get_part_border (value->theme, value->val.part.part, value->val.part.state, &border); + size = border.top; + break; + + case GTK_WIN32_PART_BORDER_RIGHT: + gtk_win32_theme_get_part_border (value->theme, value->val.part.part, value->val.part.state, &border); + size = border.right; + break; + + case GTK_WIN32_PART_BORDER_BOTTOM: + gtk_win32_theme_get_part_border (value->theme, value->val.part.part, value->val.part.state, &border); + size = border.bottom; + break; + + case GTK_WIN32_PART_BORDER_LEFT: + gtk_win32_theme_get_part_border (value->theme, value->val.part.part, value->val.part.state, &border); + size = border.left; + break; + default: g_assert_not_reached (); return 0; @@ -139,6 +168,10 @@ gtk_css_value_win32_size_print (const GtkCssValue *value, case GTK_WIN32_PART_WIDTH: case GTK_WIN32_PART_HEIGHT: + case GTK_WIN32_PART_BORDER_TOP: + case GTK_WIN32_PART_BORDER_RIGHT: + case GTK_WIN32_PART_BORDER_BOTTOM: + case GTK_WIN32_PART_BORDER_LEFT: g_string_append_printf (string, ", %d, %d", value->val.part.part, value->val.part.state); break; @@ -317,6 +350,10 @@ gtk_css_win32_size_value_parse (GtkCssParser *parser, case GTK_WIN32_PART_WIDTH: case GTK_WIN32_PART_HEIGHT: + case GTK_WIN32_PART_BORDER_TOP: + case GTK_WIN32_PART_BORDER_RIGHT: + case GTK_WIN32_PART_BORDER_BOTTOM: + case GTK_WIN32_PART_BORDER_LEFT: result = gtk_css_win32_size_value_parse_part_size (result, parser); break; diff --git a/gtk/gtkwin32draw.c b/gtk/gtkwin32draw.c index 1c761f2c31..4a28f115fa 100644 --- a/gtk/gtkwin32draw.c +++ b/gtk/gtkwin32draw.c @@ -86,6 +86,7 @@ struct _GtkWin32ThemePart { const char *class_name; gint part; gint size; + GtkBorder margins; void (* draw_func) (cairo_t *cr, int part, int state, @@ -94,9 +95,9 @@ struct _GtkWin32ThemePart { }; static GtkWin32ThemePart theme_parts[] = { - { "button", 1, 0, draw_button }, - { "button", 2, 13, draw_radio }, - { "button", 3, 13, draw_check } + { "button", 1, 0, { 3, 3, 3, 3 }, draw_button }, + { "button", 2, 13, { 0, 0, 0, 0 }, draw_radio }, + { "button", 3, 13, { 0, 0, 0, 0 }, draw_check } }; static const GtkWin32ThemePart * @@ -158,6 +159,26 @@ gtk_win32_get_theme_part_size (const char *class_name, } } +void +gtk_win32_get_theme_margins (const char *class_name, + int part, + int state, + GtkBorder *out_margins) +{ + const GtkWin32ThemePart *theme_part; + + theme_part = get_theme_part (class_name, part); + + if (theme_part) + { + *out_margins = theme_part->margins; + } + else + { + out_margins->top = out_margins->bottom = out_margins->left = out_margins->right = 0; + } +} + struct { const char *name; GdkRGBA rgba; diff --git a/gtk/gtkwin32drawprivate.h b/gtk/gtkwin32drawprivate.h index f8a11ca2ea..b2f339ad9f 100644 --- a/gtk/gtkwin32drawprivate.h +++ b/gtk/gtkwin32drawprivate.h @@ -21,6 +21,8 @@ #include #include +#include + G_BEGIN_DECLS enum { @@ -68,6 +70,10 @@ void gtk_win32_get_theme_part_size (const char int state, int *width, int *height); +void gtk_win32_get_theme_margins (const char *class_name, + int part, + int state, + GtkBorder *out_margins); void gtk_win32_get_sys_color (gint id, GdkRGBA *color); diff --git a/gtk/gtkwin32theme.c b/gtk/gtkwin32theme.c index dced7c7f10..dadc910cc2 100644 --- a/gtk/gtkwin32theme.c +++ b/gtk/gtkwin32theme.c @@ -64,6 +64,12 @@ typedef HRESULT (FAR PASCAL *GetThemePartSizeFunc) (HTHEME hTheme, RECT *prc, int eSize, SIZE *psz); +typedef HRESULT (FAR PASCAL *GetThemeBackgroundExtentFunc) (HTHEME hTheme, + HDC hdc, + int iPartId, + int iStateId, + const RECT *pContentRect, + RECT *pExtentRect); static GetThemeSysFontFunc get_theme_sys_font = NULL; static GetThemeSysColorFunc GetThemeSysColor = NULL; @@ -77,6 +83,7 @@ static IsAppThemedFunc is_app_themed = NULL; static IsThemeBackgroundPartiallyTransparentFunc is_theme_partially_transparent = NULL; static DrawThemeParentBackgroundFunc draw_theme_parent_background = NULL; static GetThemePartSizeFunc GetThemePartSize = NULL; +static GetThemeBackgroundExtentFunc GetThemeBackgroundExtent = NULL; #endif @@ -212,6 +219,7 @@ gtk_win32_theme_init (void) is_theme_partially_transparent = (IsThemeBackgroundPartiallyTransparentFunc) GetProcAddress (uxtheme_dll, "IsThemeBackgroundPartiallyTransparent"); draw_theme_parent_background = (DrawThemeParentBackgroundFunc) GetProcAddress (uxtheme_dll, "DrawThemeParentBackground"); GetThemePartSize = (GetThemePartSizeFunc) GetProcAddress (uxtheme_dll, "GetThemePartSize"); + GetThemeBackgroundExtent = (GetThemeBackgroundExtentFunc) GetProcAddress (uxtheme_dll, "GetThemeBackgroundExtent"); } if (is_app_themed && is_theme_active) @@ -387,6 +395,43 @@ gtk_win32_theme_create_surface (GtkWin32Theme *theme, return surface; } +void +gtk_win32_theme_get_part_border (GtkWin32Theme *theme, + int part, + int state, + GtkBorder *out_border) +{ +#ifdef G_OS_WIN32 + HTHEME htheme = gtk_win32_theme_get_htheme (theme); + RECT content, extent; + HDC hdc; + HRESULT res; + + if (use_xp_theme && GetThemeBackgroundExtent != NULL && htheme != NULL) + { + /* According to Wine source code, these values don't matter + * because uxtheme.dll deals with margins internally. */ + content.left = content.top = 0; + content.right = content.bottom = 100; + + hdc = GetDC (NULL); + res = GetThemeBackgroundExtent (htheme, hdc, part, state, &content, &extent); + ReleaseDC (NULL, hdc); + + if (SUCCEEDED (res)) + { + out_border->top = content.top - extent.top; + out_border->left = content.left - extent.left; + out_border->bottom = extent.bottom - content.bottom; + out_border->right = extent.right - content.right; + return; + } + } +#endif + + gtk_win32_get_theme_margins (theme->class_name, part, state, out_border); +} + void gtk_win32_theme_get_part_size (GtkWin32Theme *theme, int part, diff --git a/gtk/gtkwin32themeprivate.h b/gtk/gtkwin32themeprivate.h index b03bea835e..9ea7777366 100644 --- a/gtk/gtkwin32themeprivate.h +++ b/gtk/gtkwin32themeprivate.h @@ -49,6 +49,10 @@ cairo_surface_t * gtk_win32_theme_create_surface (GtkWin32Theme *theme, int *x_offs_out, int *y_offs_out); +void gtk_win32_theme_get_part_border (GtkWin32Theme *theme, + int part, + int state, + GtkBorder *out_border); void gtk_win32_theme_get_part_size (GtkWin32Theme *theme, int part, int state, -- 2.30.2